package com.tanhua.server.service;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import com.aliyuncs.utils.StringUtils;
import com.tanhua.autoconfig.template.OssTemplate;
import com.tanhua.commons.utils.Constants;
import com.tanhua.dubbo.api.MovementApi;
import com.tanhua.dubbo.api.RecommendUserApi;
import com.tanhua.dubbo.api.UserInfoApi;
import com.tanhua.dubbo.api.VisitorsApi;
import com.tanhua.model.domain.PageResult;
import com.tanhua.model.domain.mongo.Movement;
import com.tanhua.model.domain.mongo.Visitors;
import com.tanhua.model.domain.mysql.UserInfo;
import com.tanhua.model.domain.vo.MovementsVo;
import com.tanhua.model.domain.vo.VisitorsVo;
import com.tanhua.server.exception.BusinessException;
import com.tanhua.server.exception.ErrorResult;
import com.tanhua.server.interceptor.UserHolder;
import org.apache.dubbo.config.annotation.DubboReference;
import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author lk
 * @date 2022-03-26
 */
@Service
public class MovementsService {
    @DubboReference
    private MovementApi movementApi;
    @DubboReference
    private UserInfoApi userInfoApi;
    @DubboReference
    private VisitorsApi visitorsApi;
    @DubboReference
    private RecommendUserApi recommendUserApi;
    @Autowired
    private OssTemplate ossTemplate;
    @Autowired
    private RedisTemplate<String, String> redisTemplate;
    @Autowired
    private UserFreezeService userFreezeService;
    @Autowired
    private MqMessageService mqMessageService;

    //发布动态
    public void publishMovement(Movement movement, MultipartFile[] imageContent) throws IOException {
        String key = Constants.USER_FREEZE + movement.getUserId();
        userFreezeService.chekUserStatus("3", movement.getUserId());

        //判断发布动态的内容是否存在
        if (StringUtils.isEmpty(movement.getTextContent())) {
            //空的 则抛出异常
            throw new BusinessException(ErrorResult.contentError());
        }
        //获取当前登录的用户id
        Long userId = UserHolder.getUserId();
        //将文件内容上传到阿里云OSS，获取请求地址
        List<String> medias = new ArrayList<>();
        for (MultipartFile multipartFile : imageContent) {
            String uploadUrl = ossTemplate.upload(multipartFile.getOriginalFilename(), multipartFile.getInputStream());
            medias.add(uploadUrl);
        }
        //将数据封装到Movement对象
        movement.setUserId(userId);
        movement.setMedias(medias);
        //调用API完成发布动态
        movementApi.publish(movement);

    }

    //查询我的动态
    public PageResult findByUserId(Long userId, Integer page, Integer pageSize) {
        //根据用户id，调用API查询个人动态内容
        PageResult pageResult = movementApi.findByUserId(userId, page, pageSize);
        //获取PageResult中的item列表对象
        List<Movement> items = (List<Movement>) pageResult.getItems();
        //非空判断
        if (items == null || items.size() <= 0) {
            return pageResult;
        }
        //查询自己的详细信息
        UserInfo userInfo = userInfoApi.findById(userId);
        List<MovementsVo> vos = new ArrayList<>();
        for (Movement item : items) {
            //一个Movement构建一个Vo对象
            MovementsVo vo = MovementsVo.init(userInfo, item);
            vos.add(vo);
        }
        //构建返回值
        pageResult.setItems(vos);
        return pageResult;
    }

    //查询好友动态
    public PageResult findFriendMovements(Integer page, Integer pageSize) {
        //获取当前用户id
        Long userId = UserHolder.getUserId();
        //查询当前用户好友动态的数据列表
        List<Movement> items = movementApi.findFriendMovements(userId, page, pageSize);
        //非空判断
        if (CollUtil.isEmpty(items)) {
            return new PageResult();
        }
        //获取好友用户id
        List<Long> userIds = CollUtil.getFieldValues(items, "userId", Long.class);
        //查询好友详细信息
        Map<Long, UserInfo> userMaps = userInfoApi.findByIds(userIds, null);

        //创建一个vo对象的List集合
        List<MovementsVo> vos = new ArrayList<>();
        for (Movement item : items) {
            //获取好友对应的详细信息
            UserInfo userInfo = userMaps.get(item.getUserId());
            //构建一个MovementVo对象,调用init方法将数据封装进去
            MovementsVo vo = MovementsVo.init(userInfo, item);
            vos.add(vo);
        }
        return new PageResult(page, pageSize, 0, vos);
    }

    //推荐动态
    public PageResult findRecommendMovements(Integer page, Integer pagesize) {
        //编写redis中的key
        String redisKey = "MOVEMENTS_RECOMMEND_" + UserHolder.getUserId();
        //获取redis中的数据
        String redisData = this.redisTemplate.opsForValue().get(redisKey);
        //声明一个变量
        List<Movement> emptyList = Collections.EMPTY_LIST;

        //redis中没有推荐数据
        if (StringUtils.isEmpty(redisData)) {
            //随机插入十条数据
            emptyList = movementApi.randomMovements(pagesize);
        } else {//redis有推荐动态
            //将数据分割出来
            String[] split = redisData.split(",");
            //如果当前页数大于推荐数据的条数
            if ((page - 1) * pagesize > split.length) {
                //则返回空
                return new PageResult();
            }
            //获取大数据id
            List<Long> pids = Arrays.stream(split).skip((page - 1) * pagesize)
                    .limit(pagesize)
                    .map(e -> Convert.toLong(e))
                    .collect(Collectors.toList());
            //通过大数据id获取推荐的 动态信息
            emptyList = movementApi.findByPids(pids);
        }
        //将所有的用户id拿出来
        List<Long> userIds = CollUtil.getFieldValues(emptyList, "userId", Long.class);
        //查询用户的详细信息
        Map<Long, UserInfo> userMaps = userInfoApi.findByIds(userIds, null);
        //创建MovementsVo类型的集合接收返回数据
        List<MovementsVo> vos = new ArrayList<>();
        //循环数据列表
        for (Movement movement : emptyList) {
            //获取用户对应的详细信息
            UserInfo userInfo = userMaps.get(movement.getUserId());
            //构建一个Vo对象,调用方法将数据封装进去
            MovementsVo vo = MovementsVo.init(userInfo, movement);
            vos.add(vo);
        }
        return new PageResult(page, pagesize, 0, vos);

    }

    //查看单条动态
    public MovementsVo findMovement(String movementId) {
        ObjectId id = new ObjectId(movementId);
        //记录日志
        mqMessageService.sendLogMessage(UserHolder.getUserId(),"0202", "movement", null);
        //通过id查询单条动态
        Movement movement = movementApi.findMovement(id);
        //查询详细信息
        UserInfo userInfo = userInfoApi.findById(movement.getUserId());
        MovementsVo vo = MovementsVo.init(userInfo, movement);
        return vo;
    }

    //谁看过我(访客记录)
    public List<VisitorsVo> queryVisitorsList() {
        //从redis中取出上次查看访客信息是什么时间
        String key = Constants.VISITORS_USER;
        String hashKey = String.valueOf(UserHolder.getUserId());
        String value = (String) redisTemplate.opsForHash().get(key, hashKey);
        Long data = StringUtils.isEmpty(value) ? null : Long.valueOf(value);
        //查询看过我的人
        List<Visitors> visitorsList = visitorsApi.queryMyVisitor(UserHolder.getUserId(), data);
        //判断有没有人看过我
        if (CollUtil.isEmpty(visitorsList)) {
            //没有人 则返回一个空的
            return Collections.emptyList();
        }
        //查询查看我的人的所有详细信息
        List<Long> visitorUserIds = CollUtil.getFieldValues(visitorsList, "visitorUserId", Long.class);
        Map<Long, UserInfo> infoMap = userInfoApi.findByIds(visitorUserIds, null);
        //构造返回对象
        List<VisitorsVo> vos = new ArrayList<>();
        for (Visitors visitors : visitorsList) {
            UserInfo userInfo = infoMap.get(visitors.getVisitorUserId());
            VisitorsVo init = VisitorsVo.init(userInfo, visitors);
            vos.add(init);
        }
        return vos;
    }
}
